import {
    Scene,
    PerspectiveCamera,
    WebGLRenderer,
    AmbientLight,
    AxesHelper,
    TextureLoader,
    MeshBasicMaterial,
    LineBasicMaterial,
    Line,
    Geometry,
    Curve,
    Shape,
    ExtrudeGeometry,
    BoxGeometry,
    Mesh,
    Vector3,
    Vector2,
    CatmullRomCurve3,
    BufferGeometry,
    SphereGeometry,
    TubeBufferGeometry,
    BufferAttribute,
    ShaderMaterial,
    VertexColors,
    Color,
    Float32BufferAttribute,
    LineDashedMaterial,
    FogExp2


} from "three";

import Stats from 'three/examples/jsm/libs/stats.module.js';
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js';
import {GLTFLoader} from 'three/examples/jsm/loaders/GLTFLoader.js';
import {GUI} from 'three/examples/jsm/libs/dat.gui.module.js';

//发光效果模块导入
import {EffectComposer} from 'three/examples/jsm/postprocessing/EffectComposer.js';
import {RenderPass} from 'three/examples/jsm/postprocessing/RenderPass.js';
import {UnrealBloomPass} from "three/examples/jsm/postprocessing/UnrealBloomPass.js";
import {ShaderPass} from "three/examples/jsm/postprocessing/ShaderPass.js";

import {LineGeometry} from 'three/examples/jsm/lines/LineGeometry.js';
import {LineMaterial} from 'three/examples/jsm/lines/LineMaterial.js';
import {Line2} from 'three/examples/jsm/lines/Line2.js';
import {GeometryUtils} from 'three/examples/jsm/utils/GeometryUtils.js';

import {CSS2DRenderer, CSS2DObject} from 'three/examples/jsm/renderers/CSS2DRenderer.js';


let container, stats, controls;
let camera, scene, renderer, bactex, axehelper, labelRenderer;

//测试变量
let API = {
    x: 0.1,
    y: 0.1,
    z: 0.1
};
let sphere;
let bloomComposer, finalComposer;
let materials = [];


let car,a=0; //car为汽车1，a为0-1的浮点数用于控制汽车1位置
let car2,a2 = 0; //汽车2
let car3,a3 = 0; //汽车3

init();
animate();

function init() {

    // 基础场景布置自调用函数
    (function SceneAdd() {
        container = document.createElement('div');
        document.body.appendChild(container);

        //基础场景布置
        scene = new Scene();
        bactex = new TextureLoader().load('./src/img/bac.png');
        scene.background = bactex;
        scene.fog = new FogExp2( 0x04142a, 0.02 );

        //添加相机
        camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.25, 8000);
        camera.position.set(9.7, 2.14, -2.27517);
        camera.lookAt( new Vector3(-0.39, 0, 5.57));

        //基础渲染器
        renderer = new WebGLRenderer({antialias: true});
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.gammaOutput = false;
        container.appendChild(renderer.domElement);

        //css渲染器
        labelRenderer = new CSS2DRenderer();
        labelRenderer.setSize(window.innerWidth, window.innerHeight);
        labelRenderer.domElement.style.position = 'absolute';
        labelRenderer.domElement.style.top = '0';
        container.appendChild(labelRenderer.domElement);

        stats = new Stats();
        container.appendChild(stats.dom);

        controls = new OrbitControls(camera, labelRenderer.domElement);
        controls.target.set(-0.39, 0, 5.57);
        controls.enableDamping = true; // 开启控制阻尼
        controls.dampingFactor = 0.05; //阻尼强度
        controls.screenSpacePanning = false;
        //相机控制位置限制
        controls.minDistance = 5;
        controls.maxDistance = 30;
        controls.maxPolarAngle = Math.PI / 2.25;
        controls.update();

        //坐标轴辅助
        axehelper = new AxesHelper(5000);
        // scene.add(axehelper);

        window.addEventListener('resize', onWindowResize, false);

        function onWindowResize() {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        }

        //基础场景布置完毕
    })();


    //辅助定位球（用于控制显示场景中的坐标）
    let geometry2 = new SphereGeometry(5 / 100, 32, 32);
    let material2 = new MeshBasicMaterial({color: 0xffff00});
    sphere = new Mesh(geometry2, material2);
    // scene.add(sphere);

    //终点站位置小球，并添加css信息显示
    let t = new SphereGeometry(1 / 1000, 32, 32);
    let tsphere = new Mesh(t, material2);
    tsphere.position.set( -0.39, 0, 5.57);
    var earthDiv = document.createElement('div');
    earthDiv.className = 'target';
    earthDiv.textContent = '科博馆站';
    var earthLabel = new CSS2DObject(earthDiv);
    earthLabel.position.set(0, 0.01, 0);
    tsphere.add(earthLabel);
    scene.add(tsphere);

    //gui
    // let gui = new GUI({width: 300});
    // gui.add(API, 'x', -30, 20)
    //     .listen()
    //     .onChange(function () {
    //         sphere.position.x = API.x;
    //     });
    // gui.add(API, 'y', -10, 10)
    //     .listen()
    //     .onChange(function () {
    //         sphere.position.y = API.y;
    //     });
    // gui.add(API, 'z', -25, 20)
    //     .listen()
    //     .onChange(function () {
    //         sphere.position.z = API.z;
    //     });


    //地面加载
    let loader = new GLTFLoader();
    loader.load('./src/model/scene5.glb', function (gltf) {
        console.log(gltf);

        //地面场景放大缩小
        gltf.scene.scale.set(1 / 1000, 1 / 1000, 1 / 1000);
        //为房子指定材质
        gltf.scene.children[0].traverse(function (child) {
            if (child.isMesh) {
                child.material = new MeshBasicMaterial({
                    color: 0x3c78b4,
                    transparent: true, opacity: 0.4
                });
            }
        });
        //为expo科博站制定材质
        gltf.scene.children[2].material = new MeshBasicMaterial({
            color: 0x3c78b4,
            transparent: true, opacity: 0.4
        });
        //为ground制定材质
        gltf.scene.children[3].material = new MeshBasicMaterial({color: 0x051129});
        //为road制定材质
        gltf.scene.children[4].material = new MeshBasicMaterial({color: new Color("rgb(40,82,122)")});
        scene.add(gltf.scene);
    });
    //汽车加载
    loader.load('./src/model/carfinal.glb', function (gltf) {

        //创建一个新的汽车材质
        let material = new MeshBasicMaterial({color: 0x006600});
        //将汽车场景保存为一个变量
        car = gltf.scene;

        //汽车头顶信息显示，earthLabel为css元素
        var earthDiv = document.createElement('div');
        earthDiv.className = 'label';
        earthDiv.textContent = '1号';
        var earthLabel = new CSS2DObject(earthDiv);
        earthLabel.position.set(0, 0.1, 0);
        car.add(earthLabel);

        //汽车模型放大缩小
        gltf.scene.scale.set(1 / 50, 1 / 50, 1 / 50);
        //汽车位置更新
        gltf.scene.children[0].position.set(0, 0, 0);
        //汽车材质更新

        gltf.scene.traverse(function (child) {
            if (child.isMesh) {
                child.material = material;
            }
        });
        scene.add(gltf.scene);
    });
    //汽车2加载
    loader.load('./src/model/carfinal.glb', function (gltf) {
        // console.log(gltf);

        let material = new MeshBasicMaterial({color: 0x006600});

        car2 = gltf.scene;

        var earthDiv = document.createElement('div');
        earthDiv.className = 'label';
        earthDiv.textContent = '2号';
        var earthLabel = new CSS2DObject(earthDiv);
        earthLabel.position.set(0, 0.1, 0);
        car2.add(earthLabel);

        gltf.scene.scale.set(1 / 50, 1 / 50, 1 / 50);
        gltf.scene.children[0].position.set(0, 0, 0);
        gltf.scene.children[1].material = material;
        // gltf.scene.children[2].material = material;
        gltf.scene.traverse(function (child) {
            if (child.isMesh) {

                child.material = material;

            }
        });


        scene.add(gltf.scene);
    });
    //汽车3加载
    loader.load('./src/model/carfinal.glb', function (gltf) {
        // console.log(gltf);

        let material = new MeshBasicMaterial({color: 0x006600});

        car3 = gltf.scene;

        var earthDiv = document.createElement('div');
        earthDiv.className = 'label';
        earthDiv.textContent = '3号';
        var earthLabel = new CSS2DObject(earthDiv);
        earthLabel.position.set(0, 0.1, 0);
        car3.add(earthLabel);
        // car.rotation.y = Math.PI/2;
        // car.rotation.z = Math.PI/2;

        // let axesHelper = new AxesHelper(50);
        // car.add(axesHelper);

        gltf.scene.scale.set(1 / 50, 1 / 50, 1 / 50);
        gltf.scene.children[0].position.set(0, 0, 0);
        gltf.scene.children[1].material = material;
        // gltf.scene.children[2].material = material;
        gltf.scene.traverse(function (child) {
            if (child.isMesh) {

                child.material = material;

            }
        });


        scene.add(gltf.scene);
    });

    //后期处理
    (function () {
        //发光效果 后期处理
        /**定义bloom发光特效合成器，不输出到屏幕*/
        bloomComposer = new EffectComposer(renderer);
        bloomComposer.renderToScreen = false;
        //初始渲染过程，（位于开始，渲染好的场景作为输入）
        let renderScene = new RenderPass(scene, camera);
        //bloom发光过程
        let bloomPass = new UnrealBloomPass(new Vector2(window.innerWidth, window.innerHeight), 1.5, 0.4, 0.85);
        //发光临界值
        bloomPass.threshold = 0;
        //发光强度
        bloomPass.strength = 1;
        //发光半径
        bloomPass.radius = 0;
        //bloom发光特效合成器添加过程链（原始，发光过程）
        bloomComposer.addPass(renderScene);
        bloomComposer.addPass(bloomPass);


        /**finalPass自定义着色器处理过程，材质处理*/
        let finalPass = new ShaderPass(
            new ShaderMaterial({
                uniforms: {
                    baseTexture: {value: null},
                    bloomTexture: {value: bloomComposer.renderTarget2.texture}
                },
                vertexShader: document.getElementById('vertexshader').textContent,
                fragmentShader: document.getElementById('fragmentshader').textContent,
                defines: {}
            }), "baseTexture"
        );
        finalPass.needsSwap = true;
        //最终特效合成器（原始场景，最终过程处理）
        finalComposer = new EffectComposer(renderer);
        finalComposer.addPass(renderScene);
        finalComposer.addPass(finalPass);
    })();




    /////////////////////////////////////线路1。。。。。。。。。。
    let cur = new CatmullRomCurve3([
        new Vector3(13.25, 0, 20),
        new Vector3(8.38, 0, 4.7),
        new Vector3(7.85, 0, 4),
        new Vector3(2.07, 0, 3.82),
        new Vector3(2.07, 0, 5.93),
        new Vector3(-0.39, 0, 5.57),
    ]);
    //创建线路1，其中radius为线路的半径
    let road_g = new TubeBufferGeometry( cur, 10000, 0.01, 8, false );
    let road_m = new MeshBasicMaterial( { color: 0x05E9E2 } );
    let road = new Mesh(road_g, road_m );
    //指定名称，便于发光渲染器发光处理
    road.name = 'lightline';
    scene.add( road );

    //汽车运动定时回调
    setInterval(function () {
        //控制汽车1运动速度
        a += 0.0003;
        if (car) {
            if (a > 1) {
                a = 0;
            }

            //更新汽车位置
            cur.getPoint(a, car.position);
            car.position.y = 0.15;
            //更新汽车朝向
            car.lookAt(cur.getPoint(a + 0.001).x, -1, cur.getPoint(a + 0.001).z);
        }
    }, 12);



    //////////////////////////// 线路2......。。。。
    let cur2 = new CatmullRomCurve3([
        new Vector3(-6.88, 0, -5.3),
        new Vector3(-3.9, 0, -3.72),
        new Vector3(-2.67, 0, -3.02),
        new Vector3(-2.67, 0, -2.49),
        new Vector3(-3, 0, 1.54),
        new Vector3(-3.37, 0, 4.52),
        new Vector3(-3.37, 0, 5.05),
        new Vector3(-0.39, 0, 5.57),
    ]);
    //创建线路2，其中radius为线路的半径
    let road2_g = new TubeBufferGeometry( cur2, 10000, 0.01, 8, false );
    let road2_m = new MeshBasicMaterial( { color: 0x05E9E2 } );
    let road2 = new Mesh(road2_g, road2_m );
    //指定名称，便于发光渲染器发光处理
    road2.name = 'lightline';
    scene.add( road2 );

    //汽车运动定时回调
    setInterval(function () {
        //控制汽车2运动速度
        a2 += 0.0001;
        if (car2) {
            if (a2 > 1) {
                a2 = 0;
            }

            //汽车2位置更新，方向更新
            cur2.getPoint(a2, car2.position);
            car2.position.y = 0.15;
            car2.lookAt(cur2.getPoint(a2 + 0.001).x, -1, cur2.getPoint(a2 + 0.001).z);
        }
    }, 0.1);



    //////////////////////////// 线路3。。。。。。。。。
    let cur3 = new CatmullRomCurve3([
        new Vector3(-26.14, 0, -21.13),
        new Vector3(5.87, 0, -3.77),
        new Vector3(6.8, 0, -0.61),
        new Vector3(7.62, 0, 3.73),
        new Vector3(2.07, 0, 3.82),
        new Vector3(2.07, 0, 5.93),
        new Vector3(-0.39, 0, 5.57),
    ]);
    //创建线路3，其中radius为线路的半径
    let road3_g = new TubeBufferGeometry( cur3, 10000, 0.01, 8, false );
    let road3_m = new MeshBasicMaterial( { color: 0x05E9E2 } );
    let road3 = new Mesh(road3_g, road3_m );
    //指定名称，便于发光渲染器发光处理
    road3.name = 'lightline';
    scene.add( road3 );

    //汽车运动定时回调
    setInterval(function () {
        //a3增加大小控制汽车运动速度
        a3 += 0.0001;
        if (car3) {

            //汽车走完全程，汽车位置重置
            if (a3 > 1) {
                a3 = 0;
                // console.log(renderer.info);
            }
            //汽车3位置更新，方向更新
            cur3.getPoint(a3, car3.position);
            car3.position.y = 0.15;
            car3.lookAt(cur3.getPoint(a3 + 0.001).x, -1, cur3.getPoint(a3 + 0.001).z);
        }
    }, 1);



}


function animate() {
    requestAnimationFrame(animate);
    stats.update();
    controls.update();


    //发光效果渲染
    scene.background = null;
    let darkMaterial = new MeshBasicMaterial({color: "black"});
    scene.traverse(function (child) {
        if (child.name !== 'body' && child.name !== 'roadcurve' && child.name !== 'lightline') {
            materials[child.uuid] = child.material;
            child.material = darkMaterial;
        }

    });
    bloomComposer.render();
    //寻找场景中名称指定的非发光物体
    scene.traverse(function (child) {
        if (child.name !== 'body' && child.name !== 'roadcurve' && child.name !== 'lightline') {
            child.material = materials[child.uuid];
        }
    });
    scene.background = bactex;
    //发光后期渲染器渲染
    finalComposer.render();

    //css渲染器渲染
    labelRenderer.render(scene, camera);
}
